<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>AMQ test</title>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <script src="assets/jsunittest.js" type="text/javascript"></script>

  <script>
  var org = org || {};
  org.activemq = org.activemq || {};

  org.activemq.AmqAdapter = {
    // implement org.activemq.AmqAdapter API
    init: function(options) {},
    ajax: function(uri, options) {
      ajaxRequests[ajaxRequests.length] = { uri:uri, options:options };
    },
    
    // add additional functionality for testing.
    ajaxRequests: [],
    getRequests: function() {
      return ajaxRequests;
    },
    reset: function() {
      ajaxRequests=[];
    }
  };
  </script>
  <script src="../js/amq.js" type="text/javascript"></script>
  
  <link rel="stylesheet" href="assets/unittest.css" type="text/css" />
</head>
<body>

<div id="content">

  <div id="header">
    <h1>AMQ tests</h1>
    <p>
      This file tests amq.js.
    </p>
  </div>

  <!-- Log output (one per Runner, via {testLog: "testlog"} option)-->
  <div id="testlog"></div>
  
  <!-- Put sample/test html here -->
  <div id="sample">
  </div>
</div>

<script type="text/javascript">
  function createXmlFromString( xmlString ) {
    // http://developer.taboca.com/cases/en/client-javascript-dom-parser/
    // Mozilla and Netscape browsers
    if (document.implementation.createDocument) {
      var parser = new DOMParser()
      response = parser.parseFromString( xmlString, "text/xml")
    // MSIE
    } else if (window.ActiveXObject) {
      response = new ActiveXObject("Microsoft.XMLDOM")
      response.async="false"
      response.loadXML( xmlString )
    }
    return response;
  }
  
// <![CDATA[
  new Test.Unit.Runner({
    setup: function() {
      org.activemq.AmqAdapter.reset();
      org.activemq.Amq.init({ uri: '../amq', timeout: 30 });
    },
    
    teardown: function() {
      org.activemq.Amq.endBatch();
    },
    
    testMessagesAreSentToUrlDefinedInInit: function() { with( this ) {
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 2, requests.length );
      assertEqual( '../amq', requests[ 0 ].uri );
      assertEqual( '../amq', requests[ 1 ].uri );
    }},
    
    testFirstMessageIsAPoll: function() { with( this ) {
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      var requests = org.activemq.AmqAdapter.getRequests();
      
      assertEqual( 'get', requests[ 0 ].options.method );
      assert( requests[ 0 ].options.data.match( /timeout=1&d=\d+&r=[\d.]+/ ) );
    }},
    
    testPostIsSentIfNoBatchIsInProgress: function() { with( this ) {
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      var requests = org.activemq.AmqAdapter.getRequests();
      
      assertEqual( 2, requests.length );
      assertEqual( 'post', requests[ 1 ].options.method );
      assertEqual( 'destination=queue://test&message=<message>test</message>&type=send', requests[ 1 ].options.data );
    }},
    
    testMessagesAreDeliveredInABatchIfAjaxRequestIsInProgressWhenSendMessageIsCalled: function() { with( this ) {
      // use startBatch to indicate a previous message POST is currently in progress.
      org.activemq.Amq.startBatch();
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.sendMessage( 'queue://test2', '<message>test2</message>' );
      // endBatch is the callback once the previous POST finishes.  Triggers delivery of queued messages.
      org.activemq.Amq.endBatch();
      
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 2, requests.length );
      assertEqual( 'post', requests[1].options.method );
      assertEqual( "destination=queue://test&message=<message>test</message>&type=send&d1=queue://test2&m1=<message>test2</message>&t1=send", requests[1].options.data );
    }},
    
    testAddListenerSendsListenMessage: function() { with( this ) {
      org.activemq.Amq.addListener( 'client_id', 'topic://test', function(){} );
      var requests = org.activemq.AmqAdapter.getRequests();
      
      assertEqual( 2, requests.length );
      assertEqual( 'post', requests[1].options.method );
      assertEqual( "destination=topic://test&message=client_id&type=listen", requests[1].options.data );
    }},
    
    testAddListenerMayIncludeASelector: function() { with( this ) {
      org.activemq.Amq.addListener( 'client_id', 'topic://test', function(){}, {selector:"identifier='ALPHA'"} );
      
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 2, requests.length );
      assertEqual( 'post', requests[1].options.method );
      assertEqual( "destination=topic://test&message=client_id&type=listen", requests[1].options.data );
      assertHashEqual( { selector: "identifier='ALPHA'" }, requests[1].options.headers );
    }},
    
    testAllQueuedMessagesContainingHeadersAreDeliveredIndividuallyToPreventHeaderConflicts: function() { with( this ) {
      org.activemq.Amq.startBatch();
      org.activemq.Amq.addListener( 'client_id_1', 'topic://test1', function(){}, {selector:"identifier='ALPHA'"} );
      org.activemq.Amq.addListener( 'client_id_2', 'topic://test2', function(){}, {selector:"identifier='BRAVO'"} );
      
      // simulate 1st post returning, which triggers 2nd post.
      org.activemq.Amq.endBatch();
      
      // poll & first listen have been sent.
      assertEqual( 2, org.activemq.AmqAdapter.getRequests().length );
      
      // second listen is still in the queue.
      var queued = org.activemq.Amq.getMessageQueue();
      assertEqual( 1, queued.length );
      assertHashEqual( { selector: "identifier='BRAVO'" }, queued[ 0 ].headers );
      assertHashEqual( { destination: 'topic://test2', message: 'client_id_2', messageType: 'listen' }, queued[ 0 ].message );
      
      // when first post returns, the second listen gets sent.
      // this endBatch simulates that second post returning.
      org.activemq.Amq.endBatch();
      
      var requests = org.activemq.AmqAdapter.getRequests();
      var queued = org.activemq.Amq.getMessageQueue();
      
      assertEqual( 3, requests.length );
      assertEqual( 'post', requests[1].options.method );
      assertEqual( "destination=topic://test1&message=client_id_1&type=listen", requests[1].options.data );
      assertHashEqual( { selector: "identifier='ALPHA'" }, requests[1].options.headers );
      
      assertEqual( 'post', requests[2].options.method );
      assertEqual( "destination=topic://test2&message=client_id_2&type=listen", requests[2].options.data );
      assertHashEqual( { selector: "identifier='BRAVO'" }, requests[2].options.headers );
      
      assertEqual( 0, queued.length );
    }},
    
    // Is this desired behavior?  Message order changes from that specified by the client.
    testQueuedMessagesWithoutHeadersAreDeliveredInASinglePost: function() { with( this ) {
      org.activemq.Amq.startBatch();
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.addListener( 'client_id_1', 'topic://test1', function(){}, {selector:"identifier='ALPHA'"} );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.addListener( 'client_id_2', 'topic://test2', function(){}, {selector:"identifier='BRAVO'"} );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      
      // poll & all sendMessage calls go out first.
      org.activemq.Amq.endBatch();
      assertEqual( 2, org.activemq.AmqAdapter.getRequests().length );
      assertEqual( 2, org.activemq.Amq.getMessageQueue().length );
      
      // first listen goes next.
      org.activemq.Amq.endBatch();
      assertEqual( 3, org.activemq.AmqAdapter.getRequests().length );
      assertEqual( 1, org.activemq.Amq.getMessageQueue().length );
      
      // final listen goes out.
      org.activemq.Amq.endBatch();
      
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 4, requests.length );
      assertEqual( 0, org.activemq.Amq.getMessageQueue().length );
      
      assertEqual( "destination=queue://test&message=<message>test</message>&type=send&d1=queue://test&m1=<message>test</message>&t1=send&d2=queue://test&m2=<message>test</message>&t2=send", requests[ 1 ].options.data );
      assertHashEqual( {}, requests[ 1 ].options.headers );
      
      assertEqual( "destination=topic://test1&message=client_id_1&type=listen", requests[ 2 ].options.data );
      assertEqual( "destination=topic://test2&message=client_id_2&type=listen", requests[ 3 ].options.data );
      
    }},
    
    testSelectorFromQueuedListenerIsNotAddedToLaterMessages: function() { with( this ) {
      org.activemq.Amq.startBatch();
      org.activemq.Amq.addListener( 'client_id_1', 'topic://test1', function(){}, {selector:"identifier='ALPHA'"} );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      
      // poll & listener go out first.
      org.activemq.Amq.endBatch();
      assertEqual( 2, org.activemq.AmqAdapter.getRequests().length );
      assertEqual( 2, org.activemq.Amq.getMessageQueue().length );
      
      // 2 sendMessages go next.
      org.activemq.Amq.endBatch();
      
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 3, requests.length );
      assertEqual( 0, org.activemq.Amq.getMessageQueue().length );
      
      assertEqual( "destination=topic://test1&message=client_id_1&type=listen", requests[ 1 ].options.data );
      assertHashEqual( { selector: "identifier='ALPHA'" }, requests[ 1 ].options.headers );
      assertEqual( "destination=queue://test&message=<message>test</message>&type=send&d1=queue://test&m1=<message>test</message>&t1=send", requests[ 2 ].options.data );
      assertHashEqual( {}, requests[ 2 ].options.headers );
    }},
    
    testAddListenerWithoutSelectorWillBeBatchedWithOtherMessages: function() { with( this ) {
      org.activemq.Amq.startBatch();
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.addListener( 'client_id_1', 'topic://test1', function(){} );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.addListener( 'client_id_2', 'topic://test2', function(){} );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      
      org.activemq.Amq.endBatch();
      
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 2, requests.length );
      assertEqual( 0, org.activemq.Amq.getMessageQueue().length );
      assertEqual( "destination=queue://test&message=<message>test</message>&type=send&d1=topic://test1&m1=client_id_1&t1=listen&d2=queue://test&m2=<message>test</message>&t2=send&d3=topic://test2&m3=client_id_2&t3=listen&d4=queue://test&m4=<message>test</message>&t4=send", requests[ 1 ].options.data );
    }},
    
    testRemoveListenerSendsUnlistenMessage: function() { with( this ) {
      org.activemq.Amq.removeListener( 'client_id', 'topic://test' );
      
      var requests = org.activemq.AmqAdapter.getRequests();
      assertEqual( 2, requests.length );
      assertEqual( 'post', requests[1].options.method );
      assertEqual( "destination=topic://test&message=client_id&type=unlisten", requests[1].options.data );
    }},
    
    testAddListenerCallbackIsCalledForReceivedMessages: function() { with( this ) {
      // build an XML document like the one which the ajax implementers would pass to pollHandler
      response = createXmlFromString( '<ajax-response><response id="client_id" destination="queue://test" >test message</response></ajax-response>' );
      
      // we'll expect the callback to set this value
      var callbackValue;
      
      org.activemq.Amq.addListener( 'client_id', 'queue://test', function( msg ) { callbackValue = msg; } );
      org.activemq.Amq.testPollHandler( response );
      
      assertEqual( 'test message', callbackValue.textContent );
    }},
    
    testClientIdSpecifiedInInitIsAddedToAllAjaxRequests: function() { with( this ) {
      // need to reset to remove the poll message sent when init() is called in setup().
      org.activemq.AmqAdapter.reset();
      org.activemq.Amq.init({ uri: '../amq', timeout: 30, clientId:'uniqueClientName' });
      
      org.activemq.Amq.addListener( 'id', 'queue://test', function(){} );
      org.activemq.Amq.sendMessage( 'queue://test', '<message>test</message>' );
      org.activemq.Amq.removeListener( 'id', 'topic://test' );      
      org.activemq.Amq.endBatch();
      
      var requests = org.activemq.AmqAdapter.getRequests();
      var clientNameRegex = /clientId=uniqueClientName/;
      
      assertEqual( 3, requests.length );
      assertMatch( clientNameRegex, requests[0].options.data );
      assertMatch( clientNameRegex, requests[1].options.data );
      assertMatch( clientNameRegex, requests[2].options.data );
      
    }}
    
  }); 
// ]]>
</script>
</body>
</html>
